/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lolbuilder.mainClasses;

import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import lolbuilder.Champions.Impl.Caster;
import lolbuilder.Champions.Impl.GenericChamp;
import lolbuilder.Champions.Impl.Jax;
import lolbuilder.Champions.Interf.DummyChamp;
import lolbuilder.Items.Impl.Warmog;
import lolbuilder.Items.Interf.ItemsSuper;
import lolbuilder.build.Build;
import lolbuilder.calculation.BBadLifeStealThread;
import lolbuilder.calculation.BBadThread;
import lolbuilder.calculation.BBapThread;
import lolbuilder.calculation.BBtadThread;
import lolbuilder.calculation.BuildOrderCalculator;
import lolbuilder.calculation.LinearCompositionThread;
import lolbuilder.params.Parameters;

/**
 *
 * @author maximveron
 */
public class ItemBuildGenerator {
    public static final Integer mutex=new Integer(0);

    public static void main(String args[]) {
        LinearCompositionThread lct=new LinearCompositionThread();
        lct.start();
        Build bestBuildAd=null;
        Build bestBuildAp=null;
        Build bestBuildTankyAd=null;
        Build bestBuildAdLifeSteal=null;
        /*ArrayList<BestBuildCalculationThread> tasks=new ArrayList<BestBuildCalculationThread>();
        tasks.add(new BestBuildCalculationThread());
        tasks.add(new BestBuildCalculationThread());
        tasks.add(new BestBuildCalculationThread());
        tasks.add(new BestBuildCalculationThread());
        int dispoT=4;
        int actual=0;
         **/
       BBadLifeStealThread blst;
       BBadThread badt;
       BBapThread bapt;
       BBtadThread btadt;
        //init phase
       ArrayList<Build> results=new ArrayList<Build>();
       long nbBuildsTested=0;
       while (!lct.haveIFinished()) {
       
           /*if (dispoT<=0) {
               synchronized(mutex) {
                   try {
                        mutex.wait(1000);
                   } catch (InterruptedException ex) {
                        Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
                   }
                   for (BestBuildCalculationThread b : tasks) {
                       if (b.finished==true) {
                           if (!lct.haveIFinished()) {
                               ArrayList<Build> builds=lct.getDispoBuilds();
                               builds.addAll(b.result);
                               b.clean();
                               b.totest.addAll(builds);
                               b.runAgain();
                           } else {
                               results.addAll(b.result);
                               b.runAgain(); // will make him stop
                           }
                       }
                   }
               }
           }
           else {
               ArrayList<Build> builds=lct.getDispoBuilds();
               tasks.get(actual).totest.addAll(builds);
               tasks.get(actual).start();
               actual++;
               dispoT--;
           }
           */

           ArrayList<Build> builds=lct.getDispoBuilds();
           
           blst=new BBadLifeStealThread(builds, bestBuildAdLifeSteal);
           blst.start();

           badt=new BBadThread(builds, bestBuildAd);
           badt.start();

           bapt=new BBapThread(builds, bestBuildAp);
           bapt.start();

           btadt=new BBtadThread(builds, bestBuildTankyAd);
           btadt.start();

           
           boolean arefinished=false;
           while (arefinished==false) {
               arefinished=blst.finished && badt.finished && bapt.finished && btadt.finished;
           }
           bestBuildAd=badt.bestBuild;
           bestBuildAp=bapt.bestBuild;
           bestBuildAdLifeSteal=blst.bestBuild;
           bestBuildTankyAd=btadt.bestBuild;
       }
       /* if (bestBuildAd==null) bestBuildAd=results.get(0);
        if (bestBuildAp==null) bestBuildAp=results.get(0);
        if (bestBuildTankyAd==null) bestBuildTankyAd=results.get(0);
        if (bestBuildAdLifeSteal==null) bestBuildAdLifeSteal=results.get(0);
        bestBuildAd=ItemBuildGenerator.calculateBestDpsBuild(results,bestBuildAd);

        bestBuildAp=ItemBuildGenerator.calculateBestBurstBuild(results,bestBuildAp);

        bestBuildTankyAd=ItemBuildGenerator.calculateBestTankyAdBuild(results,bestBuildTankyAd);

        bestBuildAdLifeSteal=ItemBuildGenerator.calculateBestDpsLsBuild(results, bestBuildAdLifeSteal,20);*/
        BuildOrderCalculator bo=new BuildOrderCalculator(bestBuildAd);
        bo.start();

        GenericChamp g=new GenericChamp();//new Jax();
        bestBuildAd.applyThisBuild(g);
        g.calculateAllDatas();
        g.printAllDatas();
        System.out.println("best DpsBuild : "+bestBuildAd+"\n\n\n");

        Caster c=new Caster();
        bestBuildAp.applyThisBuild(c);
        c.calculateAllDatas();
        c.printAllDatas();
        System.out.println("best burst : "+bestBuildAp+"\n\n\n");

        GenericChamp g2=new GenericChamp();//new Jax();
        bestBuildTankyAd.applyThisBuild(g2);
        g2.calculateAllDatas();
        g2.printAllDatas();
        System.out.println("tanky score : "+ scoreCalculation(g2.dpsOver100sec, g2.timeToDie));
        System.out.println("best tankyAd : "+bestBuildTankyAd+"\n\n\n");

        g2=new GenericChamp();//new Jax();
        bestBuildAdLifeSteal.applyThisBuild(g2);
        g2.calculateAllDatas();
        g2.printAllDatas();
        System.out.println("best AdLs : "+bestBuildAdLifeSteal+"\n\n\n");

        System.out.println("\n\n\n will now calculate best order for dps");
        try {
            bo.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        Build buildOrderedAd=new Build();
        buildOrderedAd.items.addAll(bo.result.items);
        System.out.println("best build ad ordered : "+buildOrderedAd);
        return;
    }

    public static Build calculateBestDpsBuild(ArrayList<Build> builds,Build bestBuild) {
        DummyChamp g=null;
        try {
            g=Parameters.champUsedForAd.getClass().newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        Parameters.mbc.applyMasteries(g);
        Parameters.r.addAllBonus(g);
        bestBuild.applyThisBuild(g);
        g.calculateDpsOver100sec();
        float bestdmg=g.dpsOver100sec;
        Build bestBuildDpsOver100=bestBuild;

        for (int i=0;i<builds.size();i++) {
            Build b=builds.get(i);
            DummyChamp c=null;
            try {
                c=Parameters.champUsedForAd.getClass().newInstance();
            } catch (InstantiationException ex) {
                Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            Parameters.mbc.applyMasteries(c);
            Parameters.r.addAllBonus(c);   
            b.applyThisBuild(c);
            c.calculateDpsOver100sec();
            if (c.dpsOver100sec>bestdmg && c.ms>420) {
                    bestdmg=c.dpsOver100sec;
                    bestBuildDpsOver100=b;
                }
        }
        return bestBuildDpsOver100;
        
    }
    public static Build calculateBestBurstBuild(ArrayList<Build> builds,Build bestBuild) {
        DummyChamp g=null;
        try {
            g = Parameters.champUsedForAp.getClass().newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        bestBuild.applyThisBuild(g);
        g.calculateAllDatas();
        float bestdmg=g.burst;
        Build bestBuildburst=bestBuild;
        for (Build b : builds) {
            Caster c=new Caster();
            b.applyThisBuild(c);
            c.calculateBurst();
            if (c.burst>bestdmg && c.ms>420) {
                bestdmg=c.burst;
                bestBuildburst=b;
            }
        }
        return bestBuildburst;
    }

    public static Build calculateBestTankyAdBuild(ArrayList<Build> builds, Build bestBuild) {
        DummyChamp g=null;
        
        try {
            g = Parameters.champUsedForAd.getClass().newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        Parameters.r.addAllBonus(g);
        Parameters.mbc.applyMasteries(g);
        bestBuild.applyThisBuild(g);
        
        g.calculateAllDatas();
        float bestdmg=g.dpsOver100sec;
        float timeToDie=g.timeToDie;
        float score=scoreCalculation(bestdmg, timeToDie);
        Build bestBuildDpsOver100=bestBuild;

        for (int i=0;i<builds.size();i++) {
            Build b=builds.get(i);
            DummyChamp c=null;
            try {
                c = Parameters.champUsedForAd.getClass().newInstance();
            } catch (InstantiationException ex) {
                Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            Parameters.mbc.applyMasteries(c);
            Parameters.r.addAllBonus(c);
            b.applyThisBuild(c);
            c.calculateAllDatas();
            if (scoreCalculation(c.dpsOver100sec, c.timeToDie) > score && c.ms>420 && c.canResistBigBurst && c.dpsOver5sec>Parameters.minimumDPS && c.ls>Parameters.minimumLS) {
                    bestdmg=c.dpsOver100sec;
                    timeToDie=c.timeToDie;
                    bestBuildDpsOver100=b;
                    score=scoreCalculation(c.dpsOver100sec, c.timeToDie);
                }
        }
        return bestBuildDpsOver100;
    }

    public static float scoreCalculation(float damage, float timeToDie) {
        return (((damage/200000)*Parameters.ratioDmgForTrankyAd)+(timeToDie/41)*Parameters.ratioTankyForTrankyAd)/200;
    }
    

    public static Build calculateBestDpsLsBuild(ArrayList<Build> builds, Build bestBuild, int lifeSteal) {
        DummyChamp g=null;
        try {
            g = Parameters.champUsedForAd.getClass().newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        Parameters.r.addAllBonus(g);
        Parameters.mbc.applyMasteries(g);
        bestBuild.applyThisBuild(g);
        g.calculateDpsOver100sec();
        float bestdmg=g.dpsOver100sec;
        Build bestBuildDpsOver100=bestBuild;

        for (int i=0;i<builds.size();i++) {
            Build b=builds.get(i);
            DummyChamp c=null;
            try {
                c = Parameters.champUsedForAd.getClass().newInstance();
            } catch (InstantiationException ex) {
                Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(ItemBuildGenerator.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            Parameters.mbc.applyMasteries(c);
            Parameters.r.addAllBonus(c);
            b.applyThisBuild(c);
            c.calculateAllDatas();
            if (c.dpsOver100sec>bestdmg && c.ms>420 && c.ls>lifeSteal) {
                    bestdmg=c.dpsOver100sec;
                    bestBuildDpsOver100=b;
                }
        }
        return bestBuildDpsOver100;
        
    }


  
    
}
